package com.common.completableFuture;

import com.common.sort.Order;
import com.common.sort.SortUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * 日记记录工具类
 * @author zdh
 * @param <R> 结果类型
 */
@Slf4j
@NoArgsConstructor
@AllArgsConstructor
public class LogAction<R> {
    /**
     * 方法名
     */
    protected String methodName;
    /**
     * 方法实参
     */
    protected Object[] args;
    /**
     * 异常和其对应的处理器
     */
    protected List<ExHandler> exceptionHandlers=new ArrayList<>();

    public LogAction(String methodName, Object... args) {
        this.methodName = methodName;
        this.args = args;
        initExHandlers();
    }

    /**
     * 添加默认的异常处理
     */
    private void initExHandlers() {
        exceptionHandlers.add(defaultExHandler());
    }

    /**
     * @return 返回兜底异常处理器
     */
    private ExHandler defaultExHandler() {
          return ExHandler.builder()
                  .exClass(Throwable.class)
                  .order(Integer.MIN_VALUE)
                  .exConsumer(ex->{
                      log.info("methodName={}, args={}, ex={}",methodName,args,ex);
                  })
                  .build();
    }

    /**
     * 该方法只能在completableFuture包下被调用
     * @param result CompletableFuture返回得到的结果
     * @param throwable CompletableFuture得到的异常
     */
    protected void logResult(R result, Throwable throwable) {
        if(throwable!=null){
            ExHandler exHandler = getTargetExHandlers(throwable);
            exceptionHandlerCheck(throwable,exHandler);
            exHandler.consumerEx(throwable);
            return;
        }
        logSuccess(result);
    }

    private void logSuccess(R result) {
        log.info("methodName={}, args={}, result={}",methodName,args, result);
    }

    private ExHandler getTargetExHandlers(Throwable throwable) {
        for (ExHandler exceptionHandler : exceptionHandlers) {
              if(exceptionHandler.support(throwable)){
                  return exceptionHandler;
              }
        }
        return null;
    }

    /**
     * 未能找到与当前异常所匹配的处理器就抛出异常
     * @param throwable
     * @param exHandler
     */
    protected void exceptionHandlerCheck(Throwable throwable, ExHandler exHandler) {
         if(exHandler==null){
             throw new UnsupportedOperationException("未能在exceptionHandlers集合中找到当前"+throwable.getClass()+"异常类型对应的处理器");
         }
    }

    public void addExHandlers(List<ExHandler> exceptionHandlers){
          this.exceptionHandlers.addAll(exceptionHandlers);
          SortUtil.LIST_SORT(exceptionHandlers,1);
    }

    @Builder
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    protected static class ExHandler implements Order {
        /**
         * 异常类型
         */
        private Class<? extends Throwable> exClass;
        /**
         * 处理异常
         */
        private Consumer exConsumer;
        /**
         * 值越小,优先级越大
         */
        private Integer order;

        /**
         * 支持精确匹配,或者当前throwable是exClass类型的子类
         * @param throwable
         * @return
         */
        protected Boolean support(Throwable throwable){
            return exClass.isAssignableFrom(throwable.getClass());
        }

        /**
         * 交给对应消费者处理异常
         * @param ex
         */
        protected void consumerEx(Throwable ex){
             exConsumer.accept(ex);
        }

        /**
         * @return 返回order大小
         */
        @Override
        public Integer getOrder() {
            return order;
        }
    }
}
